<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>企业微信示例程序</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!--浏览器缩放-->
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <!--引入jssdk-->
    <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
    <!--引入网络工具-->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <!--调试工具-->
    <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/vConsole/3.3.4/vconsole.min.js"></script>
    <!--hash1签名工具-->
    <script src="https://cdn.bootcdn.net/ajax/libs/jshashes/1.0.8/hashes.min.js"></script>
    <!--引入vue.js-->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <style>
        body {
            margin: 10px 20px 0px 20px
        }
    </style>
</head>
<body>
<div id="app">
    <div>
        <h1>一、用户基本信息</h1>
        <div>
            <div>用户id:{{userInfo.userid}}</div>
            <div>用户姓名:{{userInfo.name}}</div>
            <div>手机号:{{userInfo.mobile}}</div>
        </div>
        <h1>二、jssdk</h1>
        <div>
            <div>已选择部门：{{selectedDepartmentList}}</div>
            <div>已选择用户：{{selectedUserList}}</div>
            <div>认证信息：{{fingerPrint}}</div>
            <button @click="enterpriseContactHandler">打开通讯录</button>
            <button @click="openWechatHandler">打开微信</button>
            <button @click="startSoterAuthentication">安全认证</button>
        </div>
        <h1>三、消息推送</h1>
        <div>
            <p>标题:<input v-model="title"></p>
            <p>内容：<input v-model="description"></p>
            <p>链接：<input v-model="url"></p>
            <p>
                <button @click="sendMessageHandler">发送</button>
            </p>
        </div>
    </div>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            baseUrl: 'http://81.70.0.48/crrcck/cgi-bin',
            oauth2Url: 'http://124.234.165.48:90',
            corpid: 'wwe70ce69225be8410',
            agentid: 1000023,
            corpsecret: 'cCl5QZe-ihMQvbBHbpUgaTU_xPK6lSYrZYYqx0uI7Xw',
            accessToken: '',
            userInfo: {},
            selectedDepartmentList: [],
            selectedUserList: [],
            title: '领奖通知',
            description: '<div class="gray">2016年9月26日</div> <div class="normal">恭喜你抽中iPhone 7一台，领奖码：xxxx</div><div class="highlight">请于2016年10月10日前联系行政同事领取</div>',
            url: 'http://www.baidu.com',
            fingerPrint:''
        },
        mounted: function () {
            console.log("mounted")
            //console控制台
            let vConsole = new VConsole();
            // `this` 指向 vm 实例
            this.getUserInfoHander();
        },
        methods: {
            async getAccessToken() {
                let resp = await axios.get(this.baseUrl + '/gettoken', {
                    params: {
                        'corpid': this.corpid, 'corpsecret': this.corpsecret
                    }
                });
                if (resp.data.errcode == 0) {
                    this.accessToken = resp.data.access_token;
                }
            },
            async getUserInfoHander() {
                await this.getAccessToken();
                let params = new URLSearchParams(location.search);
                if (params.has('code')) {
                    let code = params.get('code');
                    //code换用户信息  需要判断code是否有效
                    await this.getUserIdByCode(code);
                    //一般在页面渲染完成后 初始化jssdk
                    await this.initJssdk();
                } else {
                    //oauth2重定向地址  参考政务微信api文档
                    let redirectUri = location.href.split("#")[0];
                    let url = 'oauth2Url/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&agentid=AGENTID&state=STATE#wechat_redirect';
                    url = url.replace('CORPID', this.corpid).replace('REDIRECT_URI', redirectUri).replace('AGENTID', this.agentid).replace('oauth2Url', this.oauth2Url);
                    location.href = url;
                }
            },
            async getUserIdByCode(code) {
                let url = this.baseUrl + '/user/getuserinfo';
                let resp = await axios.get(url, {
                    params: {
                        'access_token': this.accessToken, 'code': code
                    }
                });
                if (resp.data.errcode == 0) {
                    let userId = resp.data.UserId;
                    url = this.baseUrl + '/user/get';
                    resp = await axios.get(url, {
                        params: {
                            'access_token': this.accessToken, 'userid': userId, avatar_addr: 1
                        }
                    });
                    if (resp.data.errcode == 0) {
                        this.userInfo = resp.data;
                    }
                }
            },
            //2、获取jsapiTicket/jsAgentApiTicket 需要缓存7000秒
            //注意初始化config和agentConfig的接口地址不一样
            //获取jsapiTicket
            async getJsApiTickect(url) {
                let resp = await axios.get(this.baseUrl + url, {
                    params: {
                        'access_token': this.accessToken
                    }
                })
                if (resp.data.errcode == 0) {
                    return resp.data.ticket;
                } else {
                    //异常出来
                    alert(resp.data.errmsg)
                }
            },
            //生成签名的时间戳
            createTimestamp() {
                return parseInt(new Date().getTime() / 1000);
            },
            //生成签名的随机串
            createNonceStr() {
                return Math.random().toString(36).substr(2, 15)
            },
            /**
             * 对参数对象进行字典排序
             * @param  {对象} args 签名所需参数对象
             * @return {字符串}    排序后生成字符串
             */
            raw(args) {
                var keys = Object.keys(args)
                keys = keys.sort()
                var newArgs = {}
                keys.forEach(function (key) {
                    newArgs[key.toLowerCase()] = args[key]
                })

                var string = ''
                for (var k in newArgs) {
                    string += '&' + k + '=' + newArgs[k]
                }
                string = string.substr(1)
                return string
            },
            /**
             * noncestr随机字符串，一般自己生成
             * jsapi_ticket 从政务微信服务器或者自己的缓存中
             * timestamp时间戳自己生成
             * url当前页面的url，一定要动态获取，千万不要 hardcode
             * 然后再按照字典排序，进行排序 jsapi_ticket&noncestr&timestamp&url
             * 最后sha1 加密
             */
            getSignature(jsapi_ticket, nonceStr, timestamp) {

                let ret = {
                    jsapi_ticket: jsapi_ticket,
                    nonceStr: nonceStr,
                    timestamp: timestamp,
                    url: location.href.split("#")[0]
                }
                let str = this.raw(ret);
                let SHA1 = new Hashes.SHA1;
                return SHA1.hex(str);
            },
            async initJssdk() {
                let that = this;
                //生成随机字符串
                let nonceStr = this.createNonceStr();
                //生成时间戳
                let timestamp = this.createTimestamp();

                // 获取jsApiTicket
                let jsApiTicket = await this.getJsApiTickect('/get_jsapi_ticket');
                console.log('jsApiTicket:', jsApiTicket)
                //计算config签名
                let signature = this.getSignature(jsApiTicket, nonceStr, timestamp);
                console.log('signature:', signature)
                // 初始化jssdk
                wx.config({
                    beta: true,// 调用wx.invoke形式的接口值时，该值必须为true。
                    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来，若要查看传入的参数，可以在pc端打开，参数信息会通过log打出，仅在pc端时才会打印。
                    appId: this.corpid, // 必填，企业微信的cropID
                    timestamp: timestamp, // 必填，生成签名的时间戳
                    nonceStr: nonceStr, // 必填，生成签名的随机串
                    signature: signature,// 必填，签名，见附录1
                    jsApiList: ['checkJsApi', 'agentConfig', 'selectEnterpriseContact', 'bioassayAuthentication'] // 必填，需要使用的JS接口列表，所有JS接口列表见附录
                });
                //成功回调
                wx.ready(async function () {
                    console.log('wx ready');
                    //通讯录等接口需要agent验证
                    //初始化agentConfig
                    //获取agentJsapiTicket
                    let agentJsApiTicket = await that.getJsApiTickect('/ticket/get?type=agent_config');
                    console.log('agentJsApiTicketResp', agentJsApiTicket);
                    let agentSignature = that.getSignature(agentJsApiTicket, nonceStr, timestamp);
                    wx.invoke("agentConfig", {
                        agentid: that.agentid, // 必填，企业应用的agentid
                        corpid: that.corpid,  // 必填，企业微信的corpid
                        timestamp: timestamp, // 必填，生成签名的时间戳,int类型, 如 1539100800
                        nonceStr: nonceStr, // 必填，生成签名的随机串
                        signature: agentSignature,// 必填，签名，见附录5
                    }, function (res) {
                        console.log(res);
                        //这里可以调用用户数据接口
                        if (res.err_msg != "agentConfig:ok") {
                            //错误处理
                            return;
                        }
                    });
                });
                //失败回调
                wx.error(function (res) {
                    // config信息验证失败会执行error函数，如签名过期导致验证失败，具体错误信息可以打开config的debug模式查看，
                    //也可以在返回的res参数中查看，对于SPA可以在这里更新签名。
                    console.log(res);
                });
            },
            enterpriseContactHandler() {
                let that = this;
                wx.invoke("selectEnterpriseContact", {
                        "fromDepartmentId": -1,// 必填，-1表示打开的通讯录从自己所在部门开始展示, 0表示从最上层开始
                        "mode": "single",// 必填，选择模式，single表示单选，multi表示多选
                        "type": ['department', 'user'],// 必填，选择限制类型，指定department、user中的一个或者多个
                        "selectedDepartmentIds": [],// 非必填，已选部门ID列表。用于多次选人时可重入
                        "selectedUserIds": [],// 非必填，已选用户ID列表。用于多次选人时可重入
                        "includeExternalContact": 1 //非必填，是否包含外部联系人。
                    }, function (res) {
                        console.log(res);
                        if (res.err_msg == "selectEnterpriseContact:ok") {
                            if (typeof res.result == 'string') {
                                res.result = JSON.parse(res.result) //由于目前各个终端尚未完全兼容，需要开发者额外判断result类型以保证在各个终端的兼容性
                            }
                            var selectedDepartmentList = res.result.departmentList;// 已选的部门列表
                            that.selectedDepartmentList = selectedDepartmentList;
                            for (var i = 0; i < selectedDepartmentList.length; i++) {
                                var department = selectedDepartmentList[i];
                                var departmentId = department.id;// 已选的单个部门ID
                                var departemntName = department.name;// 已选的单个部门名称
                            }
                            var selectedUserList = res.result.userList; // 已选的成员列表
                            that.selectedUserList = selectedUserList;
                            for (var i = 0; i < selectedUserList.length; i++) {
                                var user = selectedUserList[i];
                                var userId = user.id; // 已选的单个成员ID
                                var userName = user.name;// 已选的单个成员名称
                                var userAvatar = user.avatar;// 已选的单个成员头像
                                var userIsExternal = user.isExternal; //已选的单个成员是否外部联系人
                            }
                        }
                    }
                );
            },
            openWechatHandler() {
                wx.invoke('launch3rdApp', {
                        'appName': '微信', //应用显示的名称
                        'appID': 'wechat',   // iOS使用，要启动应用的scheme
                        'messageExt': 'from=weixin_webview',     // iOS使用，获取方法参考微信iOS SDK中的LaunchFromWXReq,启动App时附加的额外信息
                        'packageName': 'com.tencent.mm',    // Android使用，要启动应用的包名称
                        'param': 'webview',  //  Android使用，传递给第三方的参数，第三方通过intent.getStringExtra("launchParam")得到传过去的参数值（例如本例getStringExtra得到的结果是webview）；如出现无法唤起第三方APP的时候，可以param中附加参数excludeLauncherApp=true尝试
                    }, function (res) {
                        alert(res.err_msg);//调试日志输出
                    }
                )
            },
            startSoterAuthentication() {
                let that =this;
                wx.invoke("startSoterAuthentication", {requestAuthModes:["facial","fingerPrint"], challenge:"test_challenge",
                    authContent:"安全认证"}, function(res) {
                    that.fingerPrint = JSON.stringify(res);
                });
            },
            async sendMessage(message) {
                let resp = await axios.post(this.baseUrl + '/message/send?access_token=' + this.accessToken, message);
                console.log(resp);
            },
            sendMessageHandler() {
                let textCardMessage = {
                    "msgtype": "textcard",
                    "agentid": this.agentid,
                    "textcard": {
                        "title": this.title,
                        "description": this.description,
                        "url": this.url
                    }
                }

                let selectedUserList = this.selectedUserList;
                let tousers = [];
                if (selectedUserList && selectedUserList.length > 0) {
                    for (let i = 0; i < selectedUserList.length; i++) {
                        tousers.push(selectedUserList[i].id)
                    }
                    textCardMessage.touser = tousers.join("|");
                }
                let selectedDepartmentList = this.selectedDepartmentList;
                let toparties = [];
                if (selectedDepartmentList && selectedDepartmentList.length > 0) {
                    for (let i = 0; i < selectedDepartmentList.length; i++) {
                        toparties.push(selectedDepartmentList[i].id)
                    }
                    textCardMessage.toparty = toparties.join("|");
                }

                this.sendMessage(textCardMessage);
            }
        }
    })
</script>
</body>
</html>